package com.xxx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.xxx.constant.VerificationConstant;
import com.xxx.domain.AlipayInfo;
import com.xxx.domain.CourseUserLearn;
import com.xxx.domain.PayFlow;
import com.xxx.domain.PayOrder;
import com.xxx.dto.AlipayNotifyDto;
import com.xxx.dto.PayApplyDto;
import com.xxx.dto.UpdateOrderStateDto;
import com.xxx.exception.GlobleBussnessException;
import com.xxx.feignclients.CourseUserLearnFeignClient;
import com.xxx.mapper.PayOrderMapper;
import com.xxx.result.JSONResult;
import com.xxx.service.IAlipayInfoService;
import com.xxx.service.IPayFlowService;
import com.xxx.service.IPayOrderService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.xxx.util.AssertUtil;
import com.xxx.feign.OrderFeignApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jh
 * @since 2025-09-11
 */
@Slf4j
@Service
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {

    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private IAlipayInfoService alipayInfoService;

    @Autowired
    private IPayOrderService payOrderService;

    @Autowired
    private IPayFlowService payFlowService;

    @Autowired
    private PayOrderMapper payOrderMapper;

    @Autowired
    private OrderFeignApi orderFeignApi;

    @Autowired
    private CourseUserLearnFeignClient courseUserLearnFeignClient;


    /**
     * 检测订单支付状态
     *
     * @param orderNo
     * @return
     */
    @Override
    public JSONResult checkPayOrder(String orderNo) {
        Wrapper<PayOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no", orderNo);
        PayOrder payOrder = selectOne(wrapper);
        if (payOrder == null) {

            return JSONResult.error();
        }
        return JSONResult.success();
    }

    /**
     * 支付接口
     *
     * @param payApplyDto
     */
    @Override
    public String apply(PayApplyDto payApplyDto) {

        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(getOptions());
        try {
            Integer payType = payApplyDto.getPayType();
            String orderNo = payApplyDto.getOrderNo();
            String callUrl = payApplyDto.getCallUrl();
            //根据订单标号查询支付订单信息
            Wrapper<PayOrder> wrapper = new EntityWrapper<>();
            wrapper.eq("order_no", orderNo);
            PayOrder payOrder = payOrderService.selectOne(wrapper);

            //判断订单支付状态
            if (payOrder.getPayStatus() == VerificationConstant.PAY_STATUS_WAIT) {
                //// 2. 发起API调用（以创建当面付收款二维码为例）
                AlipayTradePagePayResponse response = Factory.Payment.Page().pay(
                        payOrder.getSubject(),
                        payOrder.getOrderNo(),
                        payOrder.getAmount().toString(),
                        callUrl); // 跳转链接
                // 3. 处理响应或异常
                if (ResponseChecker.success(response)) {
                    System.out.println("调用成功");
                    return response.getBody(); // form表单 返回付款二维码
                } else {
                    System.err.println("调用失败，原因：" + response.body + "，" + response.getBody());
                    return "支付失败";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new GlobleBussnessException("支付失败");
        }
        return "支付失败";
    }

    /**
     * 异步通知
     *
     * @param alipayNotifyDto
     * @return
     */
    @Override
    public String asyncNotify(@Valid AlipayNotifyDto alipayNotifyDto) {
        try {
            //参数校验
            //参数验签   防止数据被修改
            Map<String, String> parameters = JSONObject.parseObject(JSONObject.toJSONString(alipayNotifyDto), Map.class);
            Boolean result = Factory.Payment.Common().verifyNotify(parameters);
            //验签成功
            AssertUtil.isTrue(result, "支付宝异步通知验签失败");
            //

            //=================检验参数===========================================
            //获取参数,校验订单
            String orderNo = alipayNotifyDto.getOut_trade_no();
            Wrapper<PayOrder> wwrapper = new EntityWrapper<>();
            wwrapper.eq("order_no", orderNo);
            PayOrder payOrder = payOrderService.selectOne(wwrapper);
            AssertUtil.isNotNull(payOrder, "支付宝回调处理---支付单不能为空");
            //校验金额
            int i = payOrder.getAmount().compareTo(new BigDecimal(alipayNotifyDto.getTotal_amount()));
            AssertUtil.isEquals(i, 0, "支付宝回调处理---支付金额异常");
            //=========================检验参数===========================================

            
            //=================根据支付宝会点返回的参数进行业务处理==========================
            //待支付
            if (alipayNotifyDto.isTradeWit()) {

            }

            Date now = new Date();
            Integer payStatus = 0;
            //交易成功
            if (alipayNotifyDto.isTradeSuccess()) {
                payStatus = 1;
            }
            //交易失败
            if (alipayNotifyDto.isTradeFail()) {
                payStatus = 2;
            }

            //三个参数: 参数一:订单号， 参数二: 更新时间   参数三:支付状态
            payOrderMapper.updateStatusByOrderNo(alipayNotifyDto.getOut_trade_no(), now, payStatus);
            //保存支付流水
            PayFlow payFlow = new PayFlow();
            payFlow.setNotifyTime(now);  // 订单支付时间
            payFlow.setSubject(alipayNotifyDto.getSubject()); // 订单标题
            payFlow.setOutTradeNo(alipayNotifyDto.getOut_trade_no()); // 订单编号
            payFlow.setTradeStatus(alipayNotifyDto.getTrade_status()); // 交易状态
            payFlow.setMsg(alipayNotifyDto.getMsg()); // 结果信息
            payFlow.setCode(alipayNotifyDto.getCode()); // 错误码
            payFlow.setPaySuccess(payStatus == 1 ? true : false); // 支付状态结果
            payFlow.setTotalAmount(new BigDecimal(alipayNotifyDto.getTotal_amount())); // 支付金额
            payFlow.setResultDesc("支付状态为" + (payStatus == 1 ? true : false));
            payFlowService.insert(payFlow); //保存支付流水

            //修改订单状态=====订单服务
            UpdateOrderStateDto updateOrderStateDto = new UpdateOrderStateDto();
            updateOrderStateDto.setOrderNo(alipayNotifyDto.getOut_trade_no()); //订单号
            updateOrderStateDto.setStatusOrder(payStatus); //订单状态
            JSONResult jsonResult = orderFeignApi.updateOrderState(updateOrderStateDto);
            log.info("修改订单状态结果:{}", jsonResult);

            //t_course_user_learn 添加一条记录
            CourseUserLearn courseUserLearn = new CourseUserLearn();
            courseUserLearn.setCreateTime(now); //创建时间
            courseUserLearn.setStartTime(now); //开始时间


            courseUserLearn.setEndTime(now);   //结束时间//todo 结束时间
            courseUserLearn.setLoginId(payOrder.getUserId());
            courseUserLearn.setCourseOrderNo(alipayNotifyDto.getOut_trade_no());
            courseUserLearn.setState(0); //0已购买 1已过期
            courseUserLearn.setCourseId(Long.valueOf(payOrder.getExtParams())); //课程ID
            courseUserLearnFeignClient.saveOrUpdate(courseUserLearn);
            return "success";

            ////=================根据支付宝会点返回的参数进行业务处理==========================
        } catch (Exception e) {
            e.printStackTrace();
            throw new GlobleBussnessException("处理支付宝回调失败!");
        }
    }

    /**
     * 调用支付宝接口所需参数
     *
     * @return
     */
    private Config getOptions() {
        // 1. 设置参数（全局只需设置一次）
        //用数据库获取
        List<AlipayInfo> alipayInfos = alipayInfoService.selectList(null);
        AlipayInfo alipayInfo = alipayInfos.get(0);
        Config config = new Config();
        config.protocol = alipayInfo.getProtocol();
        config.gatewayHost = alipayInfo.getGatewayHost();
        config.signType = alipayInfo.getSignType();
        config.appId = alipayInfo.getAppId();
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        config.merchantPrivateKey = alipayInfo.getMerchantPrivateKey();
        //注：证书文件路径支持设置为文件系统中的路径或CLASS_PATH中的路径，优先从文件系统中加载，加载失败后会继续尝试从CLASS_PATH中加载
        //config.merchantCertPath = "<-- 请填写您的应用公钥证书文件路径，例如：/foo/appCertPublicKey_2019051064521003.crt -->";
        //config.alipayCertPath = "<-- 请填写您的支付宝公钥证书文件路径，例如：/foo/alipayCertPublicKey_RSA2.crt -->";
        //config.alipayRootCertPath = "<-- 请填写您的支付宝根证书文件路径，例如：/foo/alipayRootCert.crt -->";
        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        config.alipayPublicKey = alipayInfo.getAlipayPublicKey();
        //可设置异步通知接收服务地址（可选）
        config.notifyUrl = alipayInfo.getNotifyUrl();
        //可设置AES密钥，调用AES加解密相关接口时需要（可选）
        //config.encryptKey = "<-- 请填写您的AES密钥，例如：aa4BtZ4tspm2wnXLb1ThQA== -->";
        return config;
    }

    /**
     * 处理本地事务,修改订单状态,保存/修改购买记录
     */
    @Override
    @Transactional
    public void updatePayOrderAndSavePayFlow(HashMap<String, Object> map) {
        Object payFlow = map.get("payFlow");
        Object payOrder = map.get("payOrder");
        if (payOrder != null) {
            PayOrder payOrder1 = (PayOrder) payOrder;
            updateById(payOrder1);
        }
        if (payFlow != null) {
            PayFlow payFlow1 = (PayFlow) payFlow;
            payFlowService.insert(payFlow1);
        }
    }
}
